#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/spi/spi.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/of_device.h>
#include <linux/completion.h>
#include <linux/types.h>
#include <linux/dma-mapping.h>
#include <linux/proc_fs.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/clk.h>
#include <linux/rational.h>
#include <linux/reset.h>
#include <linux/slab.h>
#include <linux/stddef.h>
#include <linux/circ_buf.h>


#define CIRC_NEXT_PLACE(v,size) (((v) + 1) & ((size)-1))
#define CIRC_EMPTY(head,tail) ((head == tail) ? 1 : 0)
#define CIRC_FULL(head,tail,size) (CIRC_NEXT_PLACE(head, size) == (tail) ? 1 : 0)
/* 往head中写入数据后,调用该宏 */
#define CIRC_PUT_WRITE(head,size) \
    ({head = CIRC_NEXT_PLACE(head,size);})
/* 往从tail中读出数据后,调用该宏 */
#define CIRC_GET_READ(tail,size) \
    ({tail = CIRC_NEXT_PLACE(tail,size);})

#define VIR_UART_BUF_LEN 256

struct vir_uart_port {
	struct uart_port	port;
    struct circ_buf tx_buf;
    struct circ_buf rx_buf;
    bool tx_flag;
    int tx_irq;
    int rx_irq;
};

static struct proc_dir_entry *s3c_vir_uart_fs_entry = NULL;

static struct vir_uart_port *p_sport = NULL;

static int circ_buf_put(struct circ_buf *circ, char val)
{
    if (circ != NULL) {
        if (CIRC_FULL(circ->head, circ->tail, VIR_UART_BUF_LEN)) {
            dev_err(NULL, "circ is full\n");
            return -1;
        }
        circ->buf[circ->head] = val;
        CIRC_PUT_WRITE(circ->head, VIR_UART_BUF_LEN);
    } else {
        dev_err(NULL, "circ is NULL\n");
        return -1;
    }
    return 0;
}

static int circ_buf_get(struct circ_buf *circ, char *val)
{
    if (circ != NULL) {
        if (CIRC_EMPTY(circ->head, circ->tail)) {
            dev_err(NULL, "circ is empty\n");
            return -1;
        }
        *val = circ->buf[circ->tail];
        CIRC_GET_READ(circ->tail, VIR_UART_BUF_LEN);
    } else {
        dev_err(NULL, "circ is NULL\n");
        return -1;
    }
    return 0;
}


/*
 * Return TIOCSER_TEMT when transmitter is not busy.
 */
static unsigned int vir_tx_empty(struct uart_port *port)
{
    /* 发送上为空,返回1表示发送完成,返回0表示发送未完成 */
    return TIOCSER_TEMT;
    // struct vir_uart_port *sport = container_of(port, struct vir_uart_port, port);
    // return sport->tx_flag ? TIOCSER_TEMT : 0;
}

static void vir_set_mctrl(struct uart_port *port, unsigned int mctrl)
{

}

static unsigned int vir_get_mctrl(struct uart_port *port)
{
    return 0;
}

static void vir_stop_tx(struct uart_port *port)
{

}

#define S3C_UART_INTPND_BASE 0X4A000010

static void vir_start_tx(struct uart_port *port)
{
    /* APP Write过程
     * 使用行规程来写
     * 数据最终存入uart_state->xmit的buffer里
     * 硬件驱动中uart_ops->start_tx开始发送
     * 具体的发送方法有2种：通过DMA，或通过中断
     * 直接使能 tx empty中断，一开始tx buffer为空，在中断里填入数据
     * 写部分数据到tx fifo，使能中断，剩下的数据再中断里继续发送
     * drivers\tty\tty_io.c -> 调用到行规程的写函数
     * ldisk write -> 调用uart_write
     * 数据存入state->xmit唤醒数组中
     *
     * 发送buffer为空时触发中断,在中断函数中发送字符
     * 在实际的驱动中通过tx_irq发送数据
    */

    /* 手动触发中断发送数据 */
    /* 模拟产生TX中断 */

    // int ret = 0;
    // struct vir_uart_port *sport = container_of(port, struct vir_uart_port, port);

    // S3C2440中未实现irq_set_irqchip_state,chip中无提供该函数
#if 0
    /* IRQCHIP_STATE_PENDING状态等待CPU执行 */
    ret = irq_set_irqchip_state(sport->tx_irq, IRQCHIP_STATE_PENDING, true);
    if (ret) {
        dev_err(NULL, "Failed to set IRQ chip state\n");
    } else {
        dev_err(NULL, "IRQ chip state set successfully\n");
    }
#endif

    // 通过irq=3的按键触发TX中断函数,复制数据
    
}

static void vir_stop_rx(struct uart_port *port)
{

}

static int vir_startup(struct uart_port *port)
{
    /* 可以把中断放到该函数中注册 */ 

    return 0;
}

static void vir_shutdown(struct uart_port *port)
{

}

static void vir_set_termios(struct uart_port *port, struct ktermios *new, struct ktermios *old)
{

}

const char* vir_type(struct uart_port *port)
{
    return "JZ2440_VIRT_UART";
}

static const struct uart_ops vir_uart_pops = {
	.tx_empty	  = vir_tx_empty,
	.set_mctrl	  = vir_set_mctrl,
	.get_mctrl	  = vir_get_mctrl,
	.stop_tx	  = vir_stop_tx,
	.start_tx	  = vir_start_tx,
	.stop_rx	  = vir_stop_rx,
	.startup	  = vir_startup,
	.shutdown	  = vir_shutdown,
	.set_termios  = vir_set_termios,
	.type		  = vir_type,
};

static struct uart_driver jz_vir_uart_drv = {
	.owner		    = THIS_MODULE,
	.driver_name	= "jz_s3c2440_serial",
	.nr		        = 3,  // 平台对应的Uart的个数
	//.cons		    = S3C24XX_SERIAL_CONSOLE,
	.dev_name	    = "ttyVIRS", // 最终创建在/dev下的设备名字
	.major		    = 0,  // 让内核自动分配
	.minor		    = 0,  // 让内核自动分配
};

static irqreturn_t vir_uart_rx_handle(int irq, void *dev_id)
{
    /* 发送中断中接收数据,并唤醒行规层读取数据 */

    /**
     * APP读
     * 使用行规程来读
     * 无数据则休眠
     * UART接收到数据，产生中断
     * 中断程序从硬件上读入数据
     * 发给行规程
     * 行规程处理后存入buffer
     * 行规程唤醒APP
     * APP被唤醒后,从行规程buffer中读入数据,返回
     * drivers\tty\tty_io.c tty_read ld->ops->read
     * drivers\tty\n_tty.c 
    */

    struct vir_uart_port *sport = (struct vir_uart_port *)dev_id;
    struct tty_port *port = &sport->port.state->port;
    struct circ_buf *rx_buf = &sport->rx_buf;
    unsigned long flags = 0;
    unsigned int flg = 0;
    unsigned int len = 0;
    char val = 0;

    dev_err(NULL, "vir_uart_rx_handle running\n");

    /**
     * 真实读硬件状态
     * 得到数据
     * 在对应的uart_port中更新统计信息, 比如sport->port.icount.rx++
     * 把数据存入tty_port里的tty_buffer
     * 通知行规程来处理
    */

    /* 加锁 */
    spin_lock_irqsave(&sport->port.lock, flags);

    /* 设置TTY状态 */
    flg = TTY_NORMAL;
    /* 获取数据 */
    len = CIRC_CNT(rx_buf->head, rx_buf->tail, VIR_UART_BUF_LEN);

    dev_err(NULL, "RX_VIR_BUF LEN %d\n", len);

    /* echo "hello" > /proc/vir_uart_buf 发送hello+1个,6个字符下来 */
    while(len > 0) {
        sport->port.icount.rx++;
        circ_buf_get(rx_buf, &val);
        // 发送数据给行规层
        tty_insert_flip_char(port, (unsigned char)val, flg);
        len--;
    }
    
    spin_unlock_irqrestore(&sport->port.lock, flags);
    tty_flip_buffer_push(port);
    return IRQ_HANDLED;

}

static irqreturn_t vir_uart_tx_handle(int irq, void *dev_id)
{
    /* 发送中断中传输数据 */
    struct vir_uart_port *sport = (struct vir_uart_port *)dev_id;
    struct uart_port *port = &sport->port;
    struct circ_buf *xmit = &port->state->xmit;
    struct circ_buf *tx_buf = &sport->tx_buf;
    unsigned long flags;
    int count = 0;

    dev_err(NULL, "vir_uart_tx_handle running\n");

    /* 上锁 */
    spin_lock_irqsave(&port->lock, flags);

    /* 返回直到缓冲区末尾的计数。小心避免多次访问 head 和 tail，
     * 它们就可能在我们访问时发生变化，而不会返回不一致的结果。
    */
    count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE);

    dev_err(NULL, "vir_uart_tx_handle tx len %d\n", count);

    /* 如果没有更多要传输的数据，或者 UART 现在已经停止，则禁用 UART 并退出 */
    if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
        vir_stop_tx(port);
        goto out;
    }

    /* 如果有传输的数据发送数据并且uart stop */
    while(!uart_circ_empty(xmit) && !uart_tx_stopped(port)) {
        /* UART TX FIFO未满时,从xmit buffer取出数据写入FIFO */

        /* 真实驱动写入数据给硬件 */
        /* 虚拟驱动写数据给环形缓冲区 */
        circ_buf_put(tx_buf, xmit->buf[xmit->tail]);

        /* 从xmit的tail读数据,  tail增加 */
        xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		sport->port.icount.tx++;
    }    

out:
    spin_unlock_irqrestore(&port->lock, flags);
    return IRQ_HANDLED;
}


static ssize_t virt_uart_buf_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
    struct vir_uart_port *sport = (struct vir_uart_port *)file->private_data;
    int ret = 0;
    int len = 0;
    char tx_buf[VIR_UART_BUF_LEN];
    int i = 0;
    char val = 0;

    memset(tx_buf, 0, VIR_UART_BUF_LEN);

    if (sport) {
        len = CIRC_CNT(sport->tx_buf.head, sport->tx_buf.tail, VIR_UART_BUF_LEN);
    }

    // dev_err(NULL, "virt_uart_buf_read len %d\n", len);

    /* 从tx_buf中获取数据 */
    for(i = 0; i < len; i++) {
        circ_buf_get(&sport->tx_buf, &val);
        tx_buf[i] = val;
    }

    // dev_err(NULL, "virt_uart_buf_read tx_buf %s\n", tx_buf);

    ret = copy_to_user(buf, tx_buf, len);
    if (ret < 0) {
        dev_err(NULL, "virt_uart_buf_read failed\n");
        return ret;
    }

    /* 返回copy的数据长度 */
    return len;
}

static ssize_t virt_uart_buf_write(struct file *file, const char __user *buf, size_t size, loff_t *ppos)
{
    int ret = 0;
    char rx_buf[VIR_UART_BUF_LEN];
    int i = 0;

    struct vir_uart_port *sport = (struct vir_uart_port *)file->private_data;

    memset(rx_buf, 0, VIR_UART_BUF_LEN);
	
	/* get data */
	ret = copy_from_user(rx_buf, buf, size);
	if (ret < 0) {
        dev_err(NULL, "virt_uart_buf_write failed\n");
        return ret;
    }

    /* 复制数据到rx_buf中 */
    for(i = 0; i < size; i++) {
        circ_buf_put(&sport->rx_buf, rx_buf[i]);
    }

	/* 模拟产生RX中断 */
	// irq_set_irqchip_state(sport->rx_irq, IRQCHIP_STATE_PENDING, true);

    /* 通过按钮产生中断调用串口TX中断函数 */
    
	
	return size;
}

int virt_uart_buf_open(struct inode *inode, struct file *file)
{
    file->private_data = p_sport;

    return 0;
}

static const struct file_operations vir_uart_proc_fops = {
    .open       = virt_uart_buf_open,
	.read		= virt_uart_buf_read,
    .write      = virt_uart_buf_write,
};

static int tty_vir_uart_probe(struct platform_device *pdev)
{   
    struct device_node *np = pdev->dev.of_node;
    int ret = 0;
    struct vir_uart_port *sport;
    int txirq = 0;
    int rxirq = 0;

    /* 分配vir_uart_port */
    sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
	if (!sport)
		return -ENOMEM;

    /* 通过alias重命名获取id号 */
    if (np) {
        ret = of_alias_get_id(np, "virserial");
		if (ret >= 0)
			sport->port.line = ret;
    }
    
    dev_err(NULL, "virserial line %d\n", sport->port.line);

    /* 获取接受中断号,获取platform中第几个中断号 */
    // 通过平台的方式,从设备树中获取中断失败
    
    //rxirq = platform_get_irq(pdev, 0);
    //rxirq = irq_of_parse_and_map(np, 0);

    //dev_err(NULL, "rxirq %d\n", rxirq);

    //txirq = platform_get_irq(pdev, 1);
    //txirq = irq_of_parse_and_map(np, 1);
    //dev_err(NULL, "txirq %d\n", txirq);

    //尝试从gpio转irq尝试
    rxirq = gpio_to_irq(of_get_named_gpio(np, "eint-pins", 0));
    txirq = gpio_to_irq(of_get_named_gpio(np, "eint-pins", 1));

    dev_err(NULL, "txirq %d\n", txirq);
    dev_err(NULL, "rxirq %d\n", rxirq);

    sport->rx_irq = rxirq;
    sport->tx_irq = txirq;

    sport->port.dev = &pdev->dev;
    sport->port.iotype = UPIO_MEM;
    sport->port.irq = rxirq;
    sport->port.fifosize = 32;
    sport->port.flags = UPF_BOOT_AUTOCONF;
    sport->port.type = PORT_S3C2440;
    sport->port.ops = &vir_uart_pops;

    /* 设置发送的flag */
    sport->tx_flag = false;

    /* 分配vir_uart的tx_buf和rx_buf */
    sport->tx_buf.buf = devm_kzalloc(&pdev->dev, VIR_UART_BUF_LEN, GFP_KERNEL);
    if (sport->tx_buf.buf == NULL) {
        dev_err(&pdev->dev, "failed to virtual tx_buf\n");
        return -ENOMEM;
    }

    sport->rx_buf.buf = devm_kzalloc(&pdev->dev, VIR_UART_BUF_LEN, GFP_KERNEL);
    if (sport->rx_buf.buf == NULL) {
        dev_err(&pdev->dev, "failed to virtual rx_buf\n");
        return -ENOMEM;
    }

    /* 注册rx接收中断 */
    /* 数据在中断中接收,并把数据转发给行规层 */
    ret = devm_request_irq(&pdev->dev, rxirq, vir_uart_rx_handle, IRQF_TRIGGER_FALLING, "jz-2440-vir-uart-rx", sport);
    if (ret < 0) {
        dev_err(&pdev->dev, "failed to request rx irq: %d\n", ret);
        return ret;
    }

    /* 注册tx发送中断 */
    ret = devm_request_irq(&pdev->dev, txirq, vir_uart_tx_handle, IRQF_TRIGGER_FALLING, "jz-2440-vir-uart-tx", sport);
    if (ret < 0) {
        dev_err(&pdev->dev, "failed to request tx irq: %d\n", ret);
        return ret;
    }
    
    /* 设置platform私有数据 */
    platform_set_drvdata(pdev, sport);

    p_sport = sport;

    /* 创建/proc/file文件 */
    // s3c_vir_uart_fs_entry = proc_create("virt_uart_buf", 0, NULL, &vir_uart_proc_fops);
    s3c_vir_uart_fs_entry = proc_create_data("virt_uart_buf", 0755, NULL, &vir_uart_proc_fops, sport);
    if (!s3c_vir_uart_fs_entry) {
        dev_err(&pdev->dev, "Failed to create proc entry\n");
        return -ENOMEM;
    }
    
    /* 关联port和uart driver */
    return uart_add_one_port(&jz_vir_uart_drv, &sport->port);
}

static int tty_vir_uart_remove(struct platform_device *pdev)
{
    struct vir_uart_port *sport = platform_get_drvdata(pdev);
    /* 释放uart driver和port的关系 */
    uart_remove_one_port(&jz_vir_uart_drv, &sport->port);
    
    /* 释放proc */
    // proc_remove(s3c_vir_uart_fs_entry);
    remove_proc_entry("virt_uart_buf", NULL);
    
    return 0;
}

static const struct of_device_id tty_vir_uart[] = {
    { .compatible = "jz2440,virtual_tty_uart", },
    {},
};

static struct platform_driver tty_vir_uart_pl_driver = {
    .probe = tty_vir_uart_probe,
    .remove = tty_vir_uart_remove,
    .driver = {
        .name = "jz-tty-vir-uart",
        .of_match_table = of_match_ptr(tty_vir_uart),
    }
};

static int tty_vir_uart_init(void)
{
    /* 注册一个uart drvier驱动 */
    int ret = 0;
    ret = uart_register_driver(&jz_vir_uart_drv);
    if (ret < 0) {
        dev_err(NULL, "uart_register_driver failed\n");
        return ret;
    }

    ret = platform_driver_register(&tty_vir_uart_pl_driver);
    if (ret < 0) {
        uart_unregister_driver(&jz_vir_uart_drv);
        dev_err(NULL, "spi_vir_master_init failed\n");
        return ret;
    }

    return 0;
}

static void tty_vir_uart_exit(void)
{
    platform_driver_unregister(&tty_vir_uart_pl_driver);

    uart_unregister_driver(&jz_vir_uart_drv);
}

module_init(tty_vir_uart_init);
module_exit(tty_vir_uart_exit);

MODULE_AUTHOR("huang");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("spi master driver");




